/**
 * Created by IntelliJ IDEA.
 * User: hubiao
 * DateTime: 2018/7/25 16:50
 **/
package com.blogs.service.article.impl;

import com.blogs.common.constant.ErrorConstant;
import com.blogs.common.constant.Types;
import com.blogs.common.constant.WebConst;
import com.blogs.common.exception.BusinessException;
import com.blogs.domain.db.Comment;
import com.blogs.domain.db.Content;
import com.blogs.domain.db.Meta;
import com.blogs.domain.db.RelationShip;
import com.blogs.domain.dto.cond.ContentCond;
import com.blogs.mapper.CommentMapper;
import com.blogs.mapper.ContentMapper;
import com.blogs.mapper.RelationShipMappe;
import com.blogs.service.article.ContentService;
import com.blogs.service.meta.MetaService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;

@Service
public class ContentServiceImpl implements ContentService {

    @Resource
    private ContentMapper contentDao;

    @Resource
    private MetaService metaService;

    @Resource
    private RelationShipMappe relationShipDao;

    @Resource
    private CommentMapper commentDao;

    @Transactional(rollbackFor = Exception.class)
    @Override
    @CacheEvict(value = {"articleCache", "articleCaches"}, allEntries = true, beforeInvocation = true)
    public void addArticle(Content contentDomain) {
        if (null == contentDomain)
            throw BusinessException.withErrorCode( ErrorConstant.Common.PARAM_IS_EMPTY );

        if (StringUtils.isBlank( contentDomain.getTitle() ))
            throw BusinessException.withErrorCode( ErrorConstant.Article.TITLE_CAN_NOT_EMPTY );

        if (contentDomain.getTitle().length() > WebConst.MAX_TITLE_COUNT)
            throw BusinessException.withErrorCode( ErrorConstant.Article.TITLE_IS_TOO_LONG );

        if (StringUtils.isBlank( contentDomain.getContent() ))
            throw BusinessException.withErrorCode( ErrorConstant.Article.CONTENT_CAN_NOT_EMPTY );

        if (contentDomain.getContent().length() > WebConst.MAX_CONTENT_COUNT)
            throw BusinessException.withErrorCode( ErrorConstant.Article.CONTENT_IS_TOO_LONG );

        // 取到标签和分类
        String tags = contentDomain.getTags();
        String categories = contentDomain.getCategories();

        // 添加文章
        contentDao.addArticle( contentDomain );

        // 添加分类和标签
        int cid = contentDomain.getCid();
        metaService.addMetas( cid, tags, Types.TAG.getType() );
        metaService.addMetas( cid, categories, Types.CATEGORY.getType() );


    }

    @Override
    @Cacheable(value = "articleCache", key = "'articleById_' + #p0")
    public Content getArticleById(Integer cid) {
        if (null == cid)
            throw BusinessException.withErrorCode( ErrorConstant.Common.PARAM_IS_EMPTY );
        return contentDao.getArticleById( cid );
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = {"articleCache", "articleCaches"}, allEntries = true, beforeInvocation = true)
    public void updateArticleById(Content contentDomain) {
        // 标签和分类
        String tags = contentDomain.getTags();
        String categories = contentDomain.getCategories();

        // 更新文章
        contentDao.updateArticleById( contentDomain );
        int cid = contentDomain.getCid();
        relationShipDao.deleteRelationShipByCid( cid );
        metaService.addMetas( cid, tags, Types.TAG.getType() );
        metaService.addMetas( cid, categories, Types.CATEGORY.getType() );

    }

    @Override
    @Cacheable(value = "articleCaches", key = "'articlesByCond_' + #p1 + 'type_' + #p0.type")
    public PageInfo<Content> getArticlesByCond(ContentCond contentCond, int pageNum, int pageSize) {
        if (null == contentCond)
            throw BusinessException.withErrorCode( ErrorConstant.Common.PARAM_IS_EMPTY );
        PageHelper.startPage( pageNum, pageSize );
        List<Content> contents = contentDao.getArticleByCond( contentCond );
        PageInfo<Content> pageInfo = new PageInfo<>( contents );
        return pageInfo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = {"articleCache", "articleCaches"}, allEntries = true, beforeInvocation = true)
    public void deleteArticleById(Integer cid) {
        if (null == cid)
            throw BusinessException.withErrorCode( ErrorConstant.Common.PARAM_IS_EMPTY );
        // 删除文章
        contentDao.deleteArticleById( cid );

        // 同时要删除该 文章下的所有评论
        List<Comment> comments = commentDao.getCommentByCId( cid );
        if (null != comments && comments.size() > 0) {
            comments.forEach( comment -> {
                commentDao.deleteComment( comment.getCoid() );
            } );
        }

        // 删除标签和分类关联
        List<RelationShip> relationShips = relationShipDao.getRelationShipByCid( cid );
        if (null != relationShips && relationShips.size() > 0) {
            relationShipDao.deleteRelationShipByCid( cid );
        }


    }

    @Override
    @CacheEvict(value = {"articleCache", "articleCaches"}, allEntries = true, beforeInvocation = true)
    public void updateContentByCid(Content content) {
        if (null != content && null != content.getCid()) {
            contentDao.updateArticleById( content );
        }
    }

    @Override
    @Cacheable(value = "articleCache", key = "'articleByCategory_' + #p0")
    public List<Content> getArticleByCategory(String category) {
        if (null == category)
            throw BusinessException.withErrorCode( ErrorConstant.Common.PARAM_IS_EMPTY );
        return contentDao.getArticleByCategory( category );
    }

    @Override
    @Cacheable(value = "articleCache", key = "'articleByTags_'+ #p0")
    public List<Content> getArticleByTags(Meta tags) {
        if (null == tags)
            throw BusinessException.withErrorCode( ErrorConstant.Common.PARAM_IS_EMPTY );
        List<RelationShip> relationShip = relationShipDao.getRelationShipByMid( tags.getMid() );
        if (null != relationShip && relationShip.size() > 0) {
            return contentDao.getArticleByTags( relationShip );
        }
        return null;
    }
}
